package com.blog.zip.util;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;

import com.blog.zip.model.Option;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;

import org.apache.commons.io.IOUtils;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.parser.Parser;
import org.jsoup.safety.Whitelist;
import org.jsoup.select.NodeVisitor;


import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;

import javax.servlet.http.HttpServletRequest;

//import org.b3log.latke.Latkes;

@Slf4j
public class Markdowns {
    public static String LUTE_ENGINE_URL = "http://120.78.171.206:8249/";
    public static boolean LUTE_AVAILABLE;

    public static boolean SHOW_CODE_BLOCK_LN = false;
    public static boolean FOOTNOTES = false;
    public static boolean SHOW_TOC = false;
    public static boolean AUTO_SPACE = false;
    public static boolean FIX_TERM_TYPO = false;
    public static boolean CHINESE_PUNCT = false;
    public static boolean IMADAOM = false;
    public static boolean PARAGRAPH_BEGINNING_SPACE = false;
    public static boolean SPEECH = false;


    static String toHtmlByLute(final String markdownText) throws Exception {
        final URL url = new URL(LUTE_ENGINE_URL);
        final HttpURLConnection conn = (HttpURLConnection) url.openConnection();

        //配置
        JSONObject preference = new JSONObject();
        final String showCodeBlockLnVal = preference.optString(com.blog.zip.model.Option.ID_C_SHOW_CODE_BLOCK_LN);
        Markdowns.SHOW_CODE_BLOCK_LN = "true".equalsIgnoreCase(showCodeBlockLnVal);
        final String footnotesVal = preference.optString(com.blog.zip.model.Option.ID_C_FOOTNOTES);
        Markdowns.FOOTNOTES = "true".equalsIgnoreCase(footnotesVal);
        final String showToCVal = preference.optString(com.blog.zip.model.Option.ID_C_SHOW_TOC);
        Markdowns.SHOW_TOC = "true".equalsIgnoreCase(showToCVal);
        final String autoSpaceVal = preference.optString(com.blog.zip.model.Option.ID_C_AUTO_SPACE);
        Markdowns.AUTO_SPACE = "true".equalsIgnoreCase(autoSpaceVal);
        final String fixTermTypoVal = preference.optString(com.blog.zip.model.Option.ID_C_FIX_TERM_TYPO);
        Markdowns.FIX_TERM_TYPO = "true".equalsIgnoreCase(fixTermTypoVal);
        final String chinesePunctVal = preference.optString(com.blog.zip.model.Option.ID_C_CHINESE_PUNCT);
        Markdowns.CHINESE_PUNCT = "true".equalsIgnoreCase(chinesePunctVal);
        final String IMADAOMVal = preference.optString(com.blog.zip.model.Option.ID_C_IMADAOM);
        Markdowns.IMADAOM = "true".equalsIgnoreCase(IMADAOMVal);
        final String paragraphBeginningSpaceVal = preference.optString(com.blog.zip.model.Option.ID_C_PARAGRAPH_BEGINNING_SPACE);
        Markdowns.PARAGRAPH_BEGINNING_SPACE = "true".equalsIgnoreCase(paragraphBeginningSpaceVal);
        final String speechVal = preference.optString(Option.ID_C_SPEECH);
        Markdowns.SPEECH = "true".equalsIgnoreCase(speechVal);


//        log.info("{}", String.valueOf(Markdowns.SHOW_CODE_BLOCK_LN));
        conn.setRequestProperty("X-CodeSyntaxHighlightLineNum", "true");
        conn.setRequestProperty("X-Footnotes", String.valueOf(Markdowns.FOOTNOTES));
        conn.setRequestProperty("X-ToC", String.valueOf(Markdowns.SHOW_TOC));
        conn.setRequestProperty("X-AutoSpace", String.valueOf(Markdowns.AUTO_SPACE));
        conn.setRequestProperty("X-FixTermTypo", String.valueOf(Markdowns.FIX_TERM_TYPO));
        conn.setRequestProperty("X-ChinesePunct", String.valueOf(Markdowns.CHINESE_PUNCT));
        conn.setRequestProperty("X-IMADAOM", String.valueOf(Markdowns.IMADAOM));
        conn.setRequestProperty("X-ParagraphBeginningSpace", String.valueOf(Markdowns.PARAGRAPH_BEGINNING_SPACE));
        conn.setRequestProperty("X-HeadingID", "true");
        conn.setConnectTimeout(100);
        conn.setReadTimeout(3000);
        conn.setDoOutput(true);
        try (final OutputStream outputStream = conn.getOutputStream()) {
            IOUtils.write(markdownText, outputStream, "UTF-8");
        }

        String ret;
        try (final InputStream inputStream = conn.getInputStream()) {
            ret = IOUtils.toString(inputStream, String.valueOf(StandardCharsets.UTF_8));
        }

        conn.disconnect();
        return ret;
    }

    public static String toHTML(final String markdownText, HttpServletRequest request) {
        String html = null;
        try {
            html = toHtmlByLute(markdownText);

        } catch (final Exception e) {
            e.printStackTrace();
            //LOGGER.log(Level.WARN, "Failed to use Lute [" + LUTE_ENGINE_URL + "] for markdown [md=" + StringUtils.substring(markdownText, 0, 256) + "]: " + e.getMessage());
        }

        final Document doc = Jsoup.parseBodyFragment(html);
        doc.select("a").forEach(a -> {
            final String src = a.attr("href");
            //if (!StringUtils.startsWithIgnoreCase(src, request.getServletPath()) && !StringUtils.startsWithIgnoreCase(src, "#")) {
                a.attr("target", "_blank");
            //}
            a.removeAttr("id");
        });

        String ret = doc.body().html();
        return ret;
    }

    /**
     * Private constructor.
     */
    public Markdowns() {

    }

}
